package com.xcm.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.xcm.annotation.Operate;
import com.xcm.constant.BaseConstant;
import com.xcm.constant.SysRoleConstants;
import com.xcm.dao.RoleAuthorityMapper;
import com.xcm.dao.SysAuthorityMapper;
import com.xcm.dao.SysRoleMapper;
import com.xcm.dao.UserRoleMapper;
import com.xcm.exception.ServiceException;
import com.xcm.model.*;
import com.xcm.model.vo.SysRoleVo;
import com.xcm.page.PageInfo;
import com.xcm.service.SysRoleService;
import com.xcm.util.CheckUtil;
import com.xcm.util.SessionUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static org.apache.commons.beanutils.BeanUtils.copyProperties;

/**
 * 角色服务实现
 *
 * @author 林强
 * @date 2018-04-12 11:15
 */
@Service(value = "sysRoleService")
public class SysRoleServiceImpl implements SysRoleService {
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysAuthorityMapper sysAuthorityMapper;
    @Autowired
    private RoleAuthorityMapper roleAuthorityMapper;
    @Autowired
    private UserRoleMapper userRoleMapper;
    @Autowired
    private HttpServletRequest request;

    /**
     * 列表分页
     *
     * @param paramMap 参数
     * @param pageNum  第几页
     * @param pageSize 每页几条
     * @return
     */
    @Override
    public PageInfo<SysRole> listPage(Map<String, Object> paramMap, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        Page<SysRole> page = sysRoleMapper.listPage(paramMap);
        return PageInfo.build(page);
    }

    /**
     * 新增
     *
     * @param sysRole
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("新增角色")
    @Override
    public int save(SysRole sysRole) {
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysRole.setCreateTime(System.currentTimeMillis());
        sysRole.setUpdateTime(System.currentTimeMillis());
        sysRole.setStatus(SysRoleConstants.STATUS_USE);
        if (null != currentUser) {
            sysRole.setCreateUserId(currentUser.getUserId());
        }
        return sysRoleMapper.save(sysRole);
    }

    /**
     * 新增
     *
     * @param sysRole
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("新增角色并返回id")
    @Override
    public SysRole saveAndGetId(SysRole sysRole) {
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysRole.setCreateTime(System.currentTimeMillis());
        sysRole.setUpdateTime(System.currentTimeMillis());
        sysRole.setStatus(SysRoleConstants.STATUS_USE);
        sysRole.setAble(SysRoleConstants.ABLE_ENABLE);
        if (null != currentUser) {
            sysRole.setCreateUserId(currentUser.getUserId());
        }
        int effectRow = sysRoleMapper.saveAndGetId(sysRole);
        return effectRow > 0 ? sysRole : null;
    }

    /**
     * 新增(同时绑定权限)
     *
     * @param sysRole      新增的角色对象
     * @param authorityIds 权限id(多个以英文逗号隔开)
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("新增(同时绑定权限)")
    @Override
    public int save(SysRole sysRole, String authorityIds) {
        //新增角色
        sysRole = saveAndGetId(sysRole);
        int result = 0;
        if (null != sysRole && null != sysRole.getRoleId()) {
            result = 1;
            if (StringUtils.isNotBlank(authorityIds)) {
                //给角色绑定权限
                saveRoleAuthority(sysRole, authorityIds);
            }
        }
        return result;
    }

    /**
     * 给角色添加用户
     *
     * @param roleId  角色id
     * @param userIds 用户id(多个以英文逗号隔开)
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("给角色添加用户")
    @Override
    public int saveUserForRole(Integer roleId, String userIds) throws ServiceException {
        SysRole sysRole = sysRoleMapper.getById(roleId);
        if (null == sysRole) {
            throw new ServiceException(SysRoleConstants.ROLE_NOT_EXITS);
        }
        if (StringUtils.isBlank(sysRole.getAble())) {
            throw new ServiceException(SysRoleConstants.ROLE_NOT_ABLE_BIND_USER);
        }
        if (sysRole.getAble().equals(SysRoleConstants.ABLE_DISABLE)) {
            throw new ServiceException(SysRoleConstants.ROLE_NOT_ABLE_BIND_USER);
        }
        if (StringUtils.isBlank(userIds)) {
            throw new ServiceException(SysRoleConstants.SAVE_USER_ROLE_ERROR_NO_USER_SELECT);
        }
        int row = 0;
        // 给用户绑定角色
        userIds = userIds.trim();
        if (userIds.contains(BaseConstant.COMMA_ZH)) {
            //中文逗号改为英文逗号
            userIds = userIds.replaceAll(BaseConstant.COMMA_ZH, BaseConstant.COMMA_EN);
        }
        userIds = CheckUtil.removeLastChar(BaseConstant.COMMA_EN, userIds);
        String[] userIdArr = userIds.split(BaseConstant.COMMA_EN);
        TreeSet<String> userIdSet = new TreeSet<>(Arrays.asList(userIdArr));
        List<UserRole> userRoleList = new ArrayList<UserRole>();
        for (String userId : userIdSet) {
            UserRole userRole = new UserRole(Integer.parseInt(userId), roleId);
            //检查是否已关联
            int count = userRoleMapper.countUserRole(roleId, Integer.parseInt(userId));
            if (count <= 0) {
                userRoleList.add(userRole);
            }
        }
        if (CollectionUtils.isNotEmpty(userRoleList)) {
            row = userRoleMapper.batchSave(userRoleList);
        }
        return row;
    }

    /**
     * 刪除角色
     *
     * @param id 删除的数据的id
     * @return 大于0成功，0失败
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("刪除角色")
    @Override
    public int deleteById(Integer id) throws ServiceException {
        if (BaseConstant.SUPER_ADMIN_ROLE_ID == id) {
            throw new ServiceException(SysRoleConstants.DELETE_FAIL_SUPER_ROLE_CANNOT_DELETE);
        }
        int count = sysRoleMapper.countRoleRelationWithAuthorityAndUser(id);
        if (count > 0) {
            throw new ServiceException(SysRoleConstants.DELETE_FAIL_HAS_RELATION);
        }
        return sysRoleMapper.deleteById(id);
    }

    /**
     * 批量刪除角色
     *
     * @param roleIdList 批量删除的数据的id集合
     * @return int -1不能删除，0删除失败，大于0删除成功条数
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("批量刪除角色")
    @Override
    public int batchDeleteRole(List<Integer> roleIdList) throws ServiceException {
        int row = 0;
        for (Integer aRoleIdList : roleIdList) {
            int count = deleteById(aRoleIdList);
            row += count;
        }
        return row;
    }

    /**
     * 更新
     *
     * @param sysRole 更新的角色
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("修改角色")
    @Override
    public int update(SysRole sysRole) {
        SysUser currentUser = SessionUtils.getSessionUser(request);
        sysRole.setUpdateTime(System.currentTimeMillis());
        if (null != currentUser) {
            sysRole.setUpdateUserId(currentUser.getUserId());
        }
        return sysRoleMapper.update(sysRole);
    }

    /**
     * 更新
     *
     * @param sysRole      更新的角色
     * @param authorityIds 权限id(多个以英文逗号隔开)
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("修改角色(包括拥有的权限)")
    @Override
    public int update(SysRole sysRole, String authorityIds) {
        //更新角色
        SysRole sysRoleOld = sysRoleMapper.getById(sysRole.getRoleId());
        if (null == sysRoleOld) {
            return 1;
        }
        int effectRow = update(sysRole);
        if (effectRow > 0) {
            //清除角色已有的权限
            roleAuthorityMapper.deleteRoleAuthority(sysRole.getRoleId(), null);
            //重新给角色绑定权限
            if (StringUtils.isNotBlank(authorityIds)) {
                saveRoleAuthority(sysRole, authorityIds);
            }
        }
        return effectRow;
    }

    /**
     * 根据id查询
     *
     * @param id 主键
     * @return
     */
    @Override
    public SysRole getById(Integer id) {
        return sysRoleMapper.getById(id);
    }

    /**
     * 根据id查询角色及相关权限
     *
     * @param roleId 角色id
     * @return
     */
    @Override
    public SysRoleVo getByIdVo(Integer roleId) throws Exception {
        SysRole sysRole = sysRoleMapper.getById(roleId);
        if (null == sysRole) {
            return null;
        }
        SysRoleVo sysRoleVo = new SysRoleVo();
        copyProperties(sysRoleVo, sysRole);
        //查询相关权限
        Map<String, Object> params = new HashMap<>();
        params.put("roleId", roleId);
        List<SysAuthority> sysAuthorityList = sysAuthorityMapper.list(params);
        sysRoleVo.setAuthorityList(sysAuthorityList == null ? ListUtils.EMPTY_LIST : sysAuthorityList);
        return sysRoleVo;
    }

    /**
     * 判断是否可删除
     *
     * @param roleId 角色id
     * @return 可删除返回true, 反之false
     */
    @Override
    public boolean canDelete(Integer roleId) {
        int count = sysRoleMapper.countRoleRelationWithAuthorityAndUser(roleId);
        return count <= 0;
    }

    /**
     * 查询集合
     *
     * @param paramMap 参数map
     * @return
     */
    @Override
    public List<SysRole> list(Map<String, Object> paramMap) {
        return sysRoleMapper.list(paramMap);
    }

    /**
     * 根据用户查询角色
     *
     * @param userId
     * @return
     */
    @Override
    public List<SysRole> listByUserId(Integer userId) {
        return sysRoleMapper.listByUserId(userId);
    }

    /**
     * 批量停用或启用角色
     *
     * @param roleIdList 启用或停用的角色id集合
     * @param able       启用或停用(1启用，0停用)
     * @return 启用或停用成功条数
     */
    @Transactional(readOnly = false, rollbackFor = {Exception.class, RuntimeException.class})
    @Operate("批量停用或启用角色")
    @Override
    public int batchEnableOrDisableRole(List<Integer> roleIdList, String able) {
        return sysRoleMapper.batchEnableOrDisableRole(roleIdList, able);
    }

    /**
     * 给角色绑定权限
     *
     * @param sysRole      角色
     * @param authorityIds 权限id(多个以英文逗号隔开)
     */
    private void saveRoleAuthority(SysRole sysRole, String authorityIds) {
        authorityIds = authorityIds.trim();
        if (authorityIds.contains(BaseConstant.COMMA_ZH)) {
            //中文逗号改为英文逗号
            authorityIds = authorityIds.replaceAll(BaseConstant.COMMA_ZH, BaseConstant.COMMA_EN);
        }
        //如果以逗号结尾，清除最后一个逗号
        authorityIds = CheckUtil.removeLastChar(BaseConstant.COMMA_EN, authorityIds);
        String[] authorityIdArr = authorityIds.split(BaseConstant.COMMA_EN);
        TreeSet<String> authorityIdSet = new TreeSet<>(Arrays.asList(authorityIdArr));
        List<RoleAuthority> roleAuthorityList = new ArrayList<>();
        for (String authority : authorityIdSet) {
            RoleAuthority roleAuthority = new RoleAuthority(sysRole.getRoleId(), Integer.parseInt(authority));
            roleAuthorityList.add(roleAuthority);
        }
        if (CollectionUtils.isNotEmpty(roleAuthorityList)) {
            roleAuthorityMapper.batchSave(roleAuthorityList);
        }
    }
}
